import * as CryptoJS from "crypto-js";

// 和 cam 保持一致的 url encode
function camSafeUrlEncode(str: string) {
  return encodeURIComponent(str)
    .replace(/!/g, '%21')
    .replace(/'/g, '%27')
    .replace(/\(/g, '%28')
    .replace(/\)/g, '%29')
    .replace(/\*/g, '%2A');
}

// v4 签名
const CosAuthV4 = function (opt: any) {
  const pathname = opt.Pathname || '/';
  const expires = opt.Expires;

  let ShortBucketName = '';
  let AppId = '';
  const match = opt.Bucket.match(/^(.+)-(\d+)$/);
  if (match) {
    ShortBucketName = match[1];
    AppId = match[2];
  }

  const random = (Math.random() * Math.pow(2, 32));
  const now = (Date.now() / 1000);
  const e = now + (expires === undefined ? 900 : (expires * 1 || 0)); // 默认签名过期时间为当前时间 + 900s
  const path = '/' + AppId + '/' + ShortBucketName + encodeURIComponent(pathname).replace(/%2F/g, '/'); //多次签名这里填空
  const plainText = 'a=' + AppId + '&b=' + ShortBucketName + '&k=' + opt.SecretId + '&e=' + e + '&t=' + now + '&r=' + random + '&f=' + path;
  const sha1Res = CryptoJS.HmacSHA1(plainText, opt.SecretKey);
  const strWordArray = CryptoJS.enc.Utf8.parse(plainText);
  const resWordArray = sha1Res.concat(strWordArray);
  return resWordArray.toString(CryptoJS.enc.Base64);
};

// v5 签名
export const CosAuth = function (opt: any) {

  if (!opt.SecretId) return console.error('missing param SecretId');
  if (!opt.SecretKey) return console.error('missing param SecretKey');

  if (opt.Version === '4.0') {
    return CosAuthV4(opt);
  }

  opt = opt || {};

  const SecretId = opt.SecretId;
  const SecretKey = opt.SecretKey;
  const method = (opt.Method || 'get').toLowerCase();
  const query = opt.Query || {};
  const headers = opt.Headers || {};
  const pathname = opt.Pathname || '/';
  const expires = opt.Expires;

  const getObjectKeys = function (obj: any) {
    const list = [];
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        list.push(key);
      }
    }
    return list.sort(function (a, b) {
      a = a.toLowerCase();
      b = b.toLowerCase();
      return a === b ? 0 : (a > b ? 1 : -1);
    });
  };

  const obj2str = function (obj: any, lowerCaseKey: any) {
    let i, key, val;
    const list = [];
    const keyList = getObjectKeys(obj);
    for (i = 0; i < keyList.length; i++) {
      key = keyList[i];
      val = (obj[key] === undefined || obj[key] === null) ? '' : ('' + obj[key]);
      key = lowerCaseKey ? camSafeUrlEncode(key).toLowerCase() : camSafeUrlEncode(key);
      val = camSafeUrlEncode(val) || '';
      list.push(key + '=' + val)
    }
    return list.join('&');
  };

  // 签名有效起止时间
  const now = (new Date().getTime() / 1000) - 1;
  const exp = now + (expires === undefined ? 900 : (expires * 1 || 0)); // 默认签名过期时间为当前时间 + 900s

  // 要用到的 Authorization 参数列表
  const qSignAlgorithm = 'sha1';
  const qAk = SecretId;
  const qSignTime = now + ';' + exp;
  const qKeyTime = now + ';' + exp;
  const qHeaderList = getObjectKeys(headers).join(';').toLowerCase();
  const qUrlParamList = getObjectKeys(query).join(';').toLowerCase();

  // 签名算法说明文档：https://www.qcloud.com/document/product/436/7778
  // 步骤一：计算 SignKey
  const signKey = CryptoJS.HmacSHA1(qKeyTime, SecretKey).toString();

  // 步骤二：构成 FormatString
  const formatString = [method, pathname, obj2str(query, true), obj2str(headers, true), ''].join('\n');

  // 步骤三：计算 StringToSign
  const stringToSign = ['sha1', qSignTime, CryptoJS.SHA1(formatString).toString(), ''].join('\n');

  // 步骤四：计算 Signature
  const qSignature = CryptoJS.HmacSHA1(stringToSign, signKey).toString();

  // 步骤五：构造 Authorization
  return [
    'q-sign-algorithm=' + qSignAlgorithm,
    'q-ak=' + qAk,
    'q-sign-time=' + qSignTime,
    'q-key-time=' + qKeyTime,
    'q-header-list=' + qHeaderList,
    'q-url-param-list=' + qUrlParamList,
    'q-signature=' + qSignature
  ].join('&');

};

// const newCosAuth = cosAuth as string
// var strings = newCosAuth.split('&');
// var strings1 = strings[1].split('=');
// var strings2 = strings[2].split('=')
// var strings3 = strings[3].split('=')
// var strings6 = strings[6].split('=')
// console.log(strings2)
// console.log(strings3)
// console.log(strings6)
// const date = new Date()
// var expiration = date.toISOString();
// let policy = {
//   "expiration": expiration,
//   "conditions": [
//     {"bucket": "panda-1308597681"},
//     ["starts-with", "$key", "folder/"],
//     ["starts-with", "$Content-Type", "image/png"],
//     {"q-sign-algorithm": "sha1"},
//     {"q-ak": data.credentials.tmpSecretId},
//     {"q-sign-time": strings2[1]}
//   ]
// }
// var s = JSON.stringify(policy);
// var base = window.btoa(s);
// this.extraData!['key'] = time + '-' + uuid + extname
// this.extraData!['policy'] = base
// this.extraData!['x-cos-security-token'] = data.credentials.sessionToken
// this.extraData!['q-sign-algorithm'] = 'sha1'
// this.extraData!['q-ak'] = strings1[1]
// this.extraData!['q-key-time'] = strings3[1]
// this.extraData!['q-signature'] = strings6[1]
